'use strict';

const _ = require('lodash');

const Service = require('egg').Service;

class AttentionSvc extends Service {

  async follow(fan_name, superstar_name) {
    let now = new Date();

    let fan = await this.ctx.model.User.findOne({loginname: fan_name});
    let superstar = await this.ctx.model.User.findOne({loginname: superstar_name});


    if (!fan.followings) {
      fan.followings = [];
    }
    fan.followings.unshift({name: superstar.loginname, logo: superstar.avatar_url, last_visit_at: now, follow_at: now});
    fan.followings = this.ctx.helper.uniqueFollowingsOrFans(fan.followings);
    await fan.save();


    if (!superstar.fans) {
      superstar.fans = [];
    }
    superstar.fans.unshift({name: fan.loginname, logo: fan.avatar_url, last_visit_at: now, follow_at: now});
    superstar.fans = this.ctx.helper.uniqueFollowingsOrFans(superstar.fans);
    await superstar.save();

    // 发送消息给被订阅者
    await this.ctx.service.messageSvc.sendFollowMessage(superstar.id, fan.id);

  }

  async unfollow(fan_name, superstar_name) {
    let fan = await this.ctx.model.User.findOne({loginname: fan_name});
    let superstar = await this.ctx.model.User.findOne({loginname: superstar_name});

    let idx = -1;
    for (let i = 0; i < fan.followings.length; i++) {
      let f = fan.followings[i];
      if (f.name == superstar_name) {
        idx = i;
        break;
      }
    }
    if (idx > -1) {
      fan.followings.splice(idx, 1);
    }
    await fan.save();

    let idx2 = -1;
    for (let i = 0; i < superstar.fans.length; i++) {
      let f = superstar.fans[i];
      if (f.name == fan_name) {
        idx2 = i;
        break;
      }
    }
    if (idx2 > -1) {
      superstar.fans.splice(idx2, 1);
    }
    await superstar.save();
  }

  async listFollowings(user_name, current_page, page_size) {
    const opt = {skip: (current_page - 1) * page_size, limit: page_size, sort: {topic_count: -1, updatedAt: -1}};
    const query = {'fans.name': user_name};

    let [users, count] = await Promise.all([
      this.service.userSvc.getUsersByQuery(query, opt),
      this.service.userSvc.getCountByQuery(query, opt),
    ]);

    return [users, count];
  }


  async listFans(user_name, current_page, page_size) {
    const opt = {skip: (current_page - 1) * page_size, limit: page_size, sort: {topic_count: -1, updatedAt: -1}};
    const query = {'followings.name': user_name};

    let [users, count] = await Promise.all([
      this.service.userSvc.getUsersByQuery(query, opt),
      this.service.userSvc.getCountByQuery(query, opt),
    ]);

    return [users, count];
  }

  async updateLastVisit(user_id, superstar_name) {
    let now = new Date();
    await this.ctx.model.User.updateOne(
      {_id: user_id, 'followings.name': superstar_name},
      {$set: {'followings.$.last_visit_at': new Date()}}
    )
  }

  /**
   * 查询用户在"粉丝最后一次访问主页的时间"后有没有新增的文章, 返回unread和last_createdAt, 需要返回last_createdAt是因为后续会根据last_createdAt进行倒序排序
   * 如果有, 则表示有未读文章, 返回{last_createdAt: 最新一篇文章的创建时间, unread: true}
   * 如果没有, 则表示没有未读文章, 返回{last_createdAt: 入参传入的指定时间, unread: false}
   * @param superstar_name
   * @param last_visit_at
   * @returns {Promise<{unread: boolean, last_createdAt}>}
   */
  async getUserLastCreateTopicAfterTime(superstar_name, last_visit_at) {
    let topic = await this.ctx.model.Topic.findOne({
      author_name: superstar_name,
      createdAt: {$gt: last_visit_at}
    }, {_id: 0, createdAt: 1}).sort({_id: -1});
    if (topic) {
      return {last_createdAt: topic.createdAt, unread: true};
    } else {
      return {last_createdAt: last_visit_at, unread: false};
    }

  }

  /**
   * 查询一个用户对于他的所有关注者的访问信息
   *
   * @param followings 关注者列表
   *
   * @returns
   * name 关注者名字
   * logo 关注者的头像
   * unread 是否有未读文章
   */
  async getUnreadFollowingsInfo(user) {
    let result = [];
    let task = [];
    const followings = user.followings;
    for (let f of followings) {
      task.push(this.getUserLastCreateTopicAfterTime(f.name, f.last_visit_at));
    }
    let unread_list = await Promise.all(task);

    for (let i = 0; i < followings.length; i++) {
      result.push({
        name: followings[i].name,
        logo: followings[i].logo,
        last_createdAt: unread_list[i]['last_createdAt'],
        unread: unread_list[i]['unread']
      })
    }

    result = _.sortBy(result, item => {
      return -item.unread;
    }, item => {
      return -item.last_createdAt;
    });

    result.forEach(v => delete v.last_createdAt);

    return result;
  }

  async hasUnreadTopic(user) {
    const {followings, last_click_tab_attention} = user;

    if (followings.length == 0) {
      return false;
    }

    if (!user.last_click_tab_attention) {
      return true;
    }

    const unreadList = await Promise.all(followings.map(f =>
      this.getUserLastCreateTopicAfterTime(f.name, last_click_tab_attention)
    ));

    return unreadList.some(item => item.unread);
  }
}


module.exports = AttentionSvc;
